﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
/// <summary>
/// 这个文件包含buff类型的运行器
/// 以此扩充托管的运控功能.
/// </summary>
namespace IndustryWrapper
{
    /// <summary>
    /// 操作方法
    /// </summary>
    public enum EBuffOperate
    {
        START=1,
        STOP=2,
        PAUSE=3,
        CHANGE_OVERRIDE=4
    }
    /// <summary>
    /// 缓冲区指令的运行状态
    /// </summary>
    public enum EBuffCmdStatus
    {
        Idle=0,//空闲,还没执行
        Running=1,//运行中
        Over=2,//运行结束
        Error=3//运行错误
    }
    /// <summary>
    /// 整个缓冲区的运行状态
    /// </summary>
    public class CBuffTotalStatus
    {
        
    }
    /// <summary>
    /// 运行器
    /// </summary>
    [Serializable]
    public class CBuffManager
    {
        //公有
        public int ID = 0;//唯一的标识符
        public List<string> strList;
        //私有
        private List<CBuffCmdBase> cmdlist;
        private CBuffTotalStatus status = new CBuffTotalStatus();
        private object objLock;//锁定添加删除数据
        //如果出现XYZABC，需要映射轴号 从1开始
        public CBuffManager(int id)
        {
            cmdlist = new List<CBuffCmdBase>();
            strList = new List<string>();
            objLock = new object();
            ID = id;
        }
        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="xml"></param>
        public int read(string xml)
        {
            object p1 = CXmlSerializerManager.read(xml, typeof(CBuffManager));
            if(p1 != null)
            {
                CBuffManager o = (CBuffManager)p1;
                strList = o.strList;
                ID = o.ID;
            }
            return 0;
        }
        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public int save(string xml)
        {
            CXmlSerializerManager.save(this,xml);
            return 0;
        }
        /// <summary>
        /// 执行某个用户操作
        /// </summary>
        /// <param name="opt"></param>
        /// <returns></returns>
        public virtual bool Operate(EBuffOperate opt)
        {
            switch (opt)
            {
                case EBuffOperate.START:
                    break;
                case EBuffOperate.STOP:
                    break;
                case EBuffOperate.PAUSE:
                    break;
                case EBuffOperate.CHANGE_OVERRIDE:
                    break;
                default:
                    break;
            }
            return true;
        }
        /// <summary>
        /// 添加指令进来
        /// </summary>
        /// <param name="cmd"></param>
        public void add(CBuffCmdBase cmd)
        {
            lock (objLock)
            {
                cmdlist.Add(cmd);
            }
        }
        /// <summary>
        /// 删除指令
        /// </summary>
        /// <param name="index"></param>
        public void del(int index)
        {
            if (index >= 0 && index < cmdlist.Count)
            {
                lock (objLock)
                {
                    cmdlist.RemoveAt(index);
                }
            }
        }
        public void clear()
        {
            lock (objLock)
            {
                cmdlist.Clear();
            }
        }
        public short stop()
        {
            return 0;
        }
        public short pause()
        {
            return 0;
        }
        /// <summary>
        /// 这个函数放到一个周期的线程或者timer中
        /// </summary>
        private void run()
        {

        }
    }
    #region 指令集更广泛
    //TODO:后续完善这个功能
    /// <summary>
    /// 指令基类
    /// </summary>
    public class CBuffCmdBase
    {
        //正则表达式的字符串
        public static string regexFloat = "([+-]?\\d*\\.\\d+)(?![-+0-9\\.])";
        public static string regexLong = "(\\d+)";
        public static string markStr_Axis = "#";//轴或者坐标系的识别号
        public static IMotionPartI p1 = null;
        public static float beilv = 0.5f;//默认的系统倍率
        //其他共有变量
        public int id = 0;
        public EBuffCmdStatus status = EBuffCmdStatus.Idle;//
        /// <summary>
        /// 需要再这了注册所有子类信息
        /// </summary>
        static CBuffCmdBase()
        {

        }
        /// <summary>
        /// 通过字符串创建一个继承自CBuffCmdBase的对象
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public static CBuffCmdBase create(string cmd)
        {
            return null;
        }
        /// <summary>
        /// 静态指令类的初始化
        /// </summary>
        /// <returns></returns>
        public static bool Init()
        {
            p1 = CGlbMc.mc.ip1;
            return true;
        }
        /// <summary>
        /// 获取当前指令的状态
        /// </summary>
        /// <returns></returns>
        public virtual EBuffCmdStatus Status()
        {
            return status;
        }
        /// <summary>
        /// 执行某个用户操作
        /// </summary>
        /// <param name="opt"></param>
        /// <returns></returns>
        public virtual bool Operate(EBuffOperate opt)
        {
            return true;
        }
        /// <summary>
        /// 把指令转换成字符串 用于显示
        /// </summary>
        /// <returns></returns>
        public virtual string cmdToSimpleString()
        {
            return "";
        }
        /// <summary>
        /// 转换到复杂指令
        /// </summary>
        /// <returns></returns>
        public virtual string String()
        {
            return "";
        }

        /// <summary>
        /// 从字符串转换到数据结构中
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public virtual bool compileString(string cmd)
        {
            return true;
        }
    }
    /// <summary>
    /// TODO:还需要增加多轴的方式
    /// JOG命令
    /// 定义格式:
    /// 单轴:J#10V0.5
    /// 多轴:J#10V0.5#2V0.3;
    /// </summary>
    public class CBuffJog : CBuffCmdBase
    {
        /// <summary>
        /// 轴和速度的关系
        /// </summary>
        struct AxisAndVel
        {
            public short axis;
            public float vel;
        }
        public static string markStr_Cmd = "J";
        public static string markStrVel = "V";
        private List<AxisAndVel> prm = new List<AxisAndVel>();
        private List<CAxisRef> axis;
        public CBuffJog()
        {
            prm = new List<AxisAndVel>();
            axis = new List<CAxisRef>();
        }
        public override bool Operate(EBuffOperate opt)
        {
            int rst = 0;
            switch (opt)
            {
                case EBuffOperate.START:
                    for (int i = 0; i < axis.Count; i++)
                    {
                        rst += p1.MC_MoveJog(axis[i], prm[i].vel/axis[i].prm.maxVel * CBuffCmdBase.beilv);
                    }
                    return 0 == rst;
                case EBuffOperate.STOP:
                case EBuffOperate.PAUSE:
                    for (int i = 0; i < axis.Count; i++)
                    {
                        rst += p1.MC_MoveJog(axis[i], 0);
                    }
                    return 0 == rst;
                case EBuffOperate.CHANGE_OVERRIDE:
                    for (int i = 0; i < axis.Count; i++)
                    {
                        rst += p1.MC_MoveJog(axis[i], prm[i].vel / axis[i].prm.maxVel * CBuffCmdBase.beilv);
                    }
                    return true;
            }
            return false;
        }
        public override string String()
        {
            string rstStr = "";
            rstStr += "J";
            for (int i = 0; i < prm.Count; i++)
            {
                rstStr += "#"+prm[i].axis.ToString() + prm[i].vel.ToString("0.000");
            }
            return rstStr;
        }
        /// <summary>
        /// 返回这个指令的状态
        /// </summary>
        /// <returns></returns>
        public override EBuffCmdStatus Status()
        {
            return base.Status();
        }
        public override bool compileString(string cmd)
        {
            string tmpCmd = cmd.ToUpper();
            tmpCmd = tmpCmd.Replace(" ", "");
            if (tmpCmd.IndexOf("J") < 0)
                return false;
            tmpCmd = tmpCmd.Remove(tmpCmd.IndexOf("J"),1);
            try
            { 
                clear();
                string tmp = "";
                for (int i = 0; i < 128; i++)//最大100个轴
                {
                    AxisAndVel p = new AxisAndVel();
                    tmp = Regex.Match(tmpCmd, "(#)" + regexLong).Value;
                    if (tmp != "")
                    {
                        p.axis = short.Parse(tmp);
                        tmpCmd = tmpCmd.Remove(0, tmp.Length + 1);
                        if (tmpCmd.Length >0 && tmpCmd[0] =='V')
                        {
                            tmpCmd = Regex.Match(tmpCmd, "(V)" + regexFloat).Value;
                            p.vel = float.Parse(tmpCmd);
                        }
                        else
                        {
                            p.vel = float.MaxValue;
                        }   
                    }
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        private void clear()
        {
            axis.Clear();
            prm.Clear();
        }
    }
    /// <summary>
    /// 绝对运动
    /// 定义格式：
    /// 单轴:ABS15P100V0.5
    /// 多轴:
    /// </summary>
    class CBufAbs:CBuffCmdBase
    {
        public static string markStr = "ABS";
        public List<int> axis = new List<int>();
        public List<double> pos = new List<double>();
        public List<float> vel = new List<float>();
        private List<CAxisRef> refList = new List<CAxisRef>();
        public override bool Operate(EBuffOperate opt)
        {
            if (p1 == null)
                return false;
            //第一次进入的时候,构建所有的轴引用
            if (refList.Count == 0)
            {
                foreach (var item in axis)
                {
                    CAxisRef a = new CAxisRef(item);
                    refList.Add(a);
                }
            }
            //执行动作
            int rst = 0;
            switch (opt)
            {
                case EBuffOperate.START:
                    for (int i = 0; i < refList.Count; i++)
                    {
                        rst += p1.MC_MoveAbs(refList[i], pos[i], vel[i]*beilv);
                        if (rst != 0)
                            break;
                    }
                    if (rst != 0)
                    {
                        for (int i = 0; i < refList.Count; i++)
                        {
                            rst += p1.MC_EStop(refList[i]);
                        }
                    }
                    return rst == 0;
                case EBuffOperate.STOP:
                    for (int i = 0; i < refList.Count; i++)
                    {
                        p1.MC_MoveAbs(refList[i], pos[i], 0);
                    }
                    return true;
                case EBuffOperate.PAUSE:
                    for (int i = 0; i < refList.Count; i++)
                    {
                        p1.MC_MoveAbs(refList[i], pos[i], 0);
                    }
                    return true;
                case EBuffOperate.CHANGE_OVERRIDE:
                    for (int i = 0; i < refList.Count; i++)
                    {
                        p1.MC_MoveAbs(refList[i], pos[i], vel[i] * beilv);
                    }
                    return true;
            }
            return false;
        }
        public override string String()
        {
            return "ABS";// + axis.ToString() + "V" + vel.ToString("0.00");
        }
        public override bool compileString(string cmd)
        {
            //string tmpCmd = cmd.ToUpper();
            //tmpCmd = tmpCmd.Replace(" ", "");
            //if (tmpCmd.IndexOf("J") < 0)
            //    return false;
            //try
            //{
            //    short tmpAxis = short.Parse(Regex.Match(Regex.Match(tmpCmd, "(J)" + regexLong).Value, regexLong).Value);
            //    float tmpVel = float.Parse(Regex.Match(Regex.Match(tmpCmd, "(V)" + regexFloat).Value, regexFloat).Value);
            //    axis = tmpAxis;
            //    vel = tmpVel;
            //}
            //catch (Exception)
            //{
            //    axis = 0;
            //    vel = 0.5f;
            //    return false;
            //}
            return true;
        }
    }
    
    class CBuffCam : CBuffCmdBase
    {

    }
    class CBuffDo : CBuffCmdBase
    {

    }
    class CBuffDi : CBuffCmdBase
    {

    }
    class CBuffDelay : CBuffCmdBase
    {
        private int delayMs = 100;//延迟一定时间
        public CBuffDelay(int time)
        {

        }
        /// <summary>
        /// 重载了操作
        /// </summary>
        /// <param name="opt"></param>
        /// <returns></returns>
        public override bool Operate(EBuffOperate opt)
        {
            switch (opt)
            {
                case EBuffOperate.START:
                    break;
                case EBuffOperate.STOP:
                    break;
                case EBuffOperate.PAUSE:
                    break;
                case EBuffOperate.CHANGE_OVERRIDE:
                    break;
                default:
                    break;
            }
            return base.Operate(opt);
        }
    }
    class CBuffJump : CBuffCmdBase
    {

    }
    /// <summary>
    /// 报告错误消息  等待用户处理
    /// </summary>
    class CBuffReport: CBuffCmdBase
    {

    }
    class CBuffCrd: CBuffCmdBase
    {
        /// <summary>
        /// 坐标系映射
        /// </summary>
        public int mapX = 0, mapY = 0, mapZ = 0, mapA = 0, mapB = 0, mapC = 0;
    }
    #endregion
    #region 指令集G代码
    /// <summary>
    /// 基础指令
    /// </summary>
    public class CGBase
    {
        //公用参数
        public static double defaultVel = 1.0;//默认速度
        public static bool prmAbsOrRel = false;//绝对运动还是相对运动
        //正则表达式的字符串
        public static string regexFloat = "([+-]?\\d*\\.\\d+)(?![-+0-9\\.])";
        public static string regexLong = "(\\d+)";
        //公有变量
        public bool isSingleCmd = true;//是单个指令 或者 和下一条指令不连续
        public double cutVel = 10;//MM/S
        /// <summary>
        /// 字符串类型
        /// </summary>
        public static List<string> cmdBaseStr = new List<string>();//用来判断类型
        public static List<string> cmdClassStr = new List<string>();//用来创建新类
        /// <summary>
        /// 注册新指令用的
        /// 每个新类的静态构造函数中调用
        /// 指令都要在这里注册
        /// </summary>
        /// <param name="cmdStr"></param>
        /// <param name="classStr"></param>
        public static void registerCommand(string cmdStr, string classStr)
        {
            cmdBaseStr.Add(cmdStr);
            cmdClassStr.Add(classStr);
        }
        /// <summary>
        /// 通过名称创建类型
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public static CGBase createClass(string cmd)
        {
            for (int i = 0; i < cmdBaseStr.Count; i++)
            {
                if (cmdBaseStr[i].IndexOf(",") > 0)
                {
                    string[] divStr = cmdBaseStr[i].Split(',');
                    foreach (var item in divStr)
                    {
                        if (cmd.IndexOf(item) >= 0)
                        {
                            Type type = Type.GetType("IndustryWrapper." + cmdClassStr[i], true, true);
                            CGBase obj = (CGBase)Activator.CreateInstance(type);
                            obj.compileString(cmd);
                            return obj;
                        }
                    }
                }
                else if (cmd.IndexOf(cmdBaseStr[i]) >= 0)
                {
                    Type type = Type.GetType("IndustryWrapper." + cmdClassStr[i], true, true);
                    CGBase obj = (CGBase)Activator.CreateInstance(type);
                    obj.compileString(cmd);
                    return obj;
                }
            }
            return null;
        }
        /// <summary>
        /// 把指令转换成字符串 用于显示
        /// </summary>
        /// <returns></returns>
        public virtual string cmdToSimpleString()
        {
            return "";
        }
        /// <summary>
        /// 转换到复杂指令
        /// </summary>
        /// <returns></returns>
        public virtual string cmdToComplexString()
        {
            return "";
        }
        public virtual void rotate(CPoint3D center, double angle)
        {
        }
        public virtual void translate(double distX, double distY, double addtionZ)
        {
        }
        /// <summary>
        /// 从字符串转换到数据结构中
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public virtual bool compileString(string cmd)
        {
            return true;
        }
    }    
    /// <summary>
    /// 快速定位的G代码
    /// </summary>
    public class CG00:CGBase
    {
        public static string cmdMarkStr = "G00";
        public CPoint6D ept = new CPoint6D();//三点构造圆的第2个点 = MAXvalue的时候表示没启用
        public double vel = 1.0;
        public int dimension = 3;
        static CG00()
        {
            CGBase.registerCommand(cmdMarkStr, "CG00");
        }
        public CG00()
        {
            ept.x = ept.y = ept.z = ept.a = ept.b = ept.c = double.MaxValue;
        }
        public override bool compileString(string cmd)
        {
            string nospace = cmd.Replace(" ", "");
            nospace = nospace.ToUpper();
            if (nospace.IndexOf("G0") < 0 && nospace.IndexOf("G00") < 0)
                return false;
            string tmp1 = "";
            int tmpDimension = 0;
            #region X坐标
            tmp1 = Regex.Match(nospace, "(X)" + regexFloat).Value;
            if (tmp1 != "")
            {
                tmp1 = tmp1.Replace("X", "");
                ept.x = double.Parse(tmp1);
                tmpDimension++;
            }
            else
            {
                tmp1 = Regex.Match(nospace, "(X)" + regexLong).Value;
                if (tmp1 != "")
                {
                    tmp1 = tmp1.Replace("X", "");
                    ept.x = double.Parse(tmp1);
                    tmpDimension++;
                }
            }
            #endregion
            #region Y坐标
            tmp1 = Regex.Match(nospace, "(Y)" + regexFloat).Value;
            if (tmp1 != "")
            {
                tmp1 = tmp1.Replace("Y", "");
                ept.y = double.Parse(tmp1);
                tmpDimension++;
            }
            else
            {
                tmp1 = tmp1.Replace("Y", "");
                tmp1 = Regex.Match(nospace, "(Y)" + regexLong).Value;
                if (tmp1 != "")
                {
                    ept.y = double.Parse(tmp1);
                    tmpDimension++;
                }
            }
            #endregion
            #region Z坐标
            tmp1 = Regex.Match(nospace, "(Z)" + regexFloat).Value;
            if (tmp1 != "")
            {
                tmp1 = tmp1.Replace("Z", "");
                ept.z = double.Parse(tmp1);
                tmpDimension++;
            }
            else
            {
                tmp1 = Regex.Match(nospace, "(Z)" + regexLong).Value;
                if (tmp1 != "")
                {
                    tmp1 = tmp1.Replace("Z", "");
                    ept.z = double.Parse(tmp1);
                    tmpDimension++;
                }
            }
            #endregion
            #region A坐标
            tmp1 = Regex.Match(nospace, "(A)" + regexFloat).Value;
            if (tmp1 != "")
            {
                tmp1 = tmp1.Replace("A", "");
                ept.a = double.Parse(tmp1);
                tmpDimension++;
            }
            else
            {
                tmp1 = Regex.Match(nospace, "(A)" + regexLong).Value;
                if (tmp1 != "")
                {
                    tmp1 = tmp1.Replace("A", "");
                    ept.a = double.Parse(tmp1);
                    tmpDimension++;
                }
            }
            #endregion
            #region B坐标
            tmp1 = Regex.Match(nospace, "(B)" + regexFloat).Value;
            if (tmp1 != "")
            {
                tmp1 = tmp1.Replace("B", "");
                ept.b = double.Parse(tmp1);
                tmpDimension++;
            }
            else
            {
                tmp1 = Regex.Match(nospace, "(B)" + regexLong).Value;
                if (tmp1 != "")
                {
                    tmp1 = tmp1.Replace("B", "");
                    ept.b = double.Parse(tmp1);
                    tmpDimension++;
                }
            }
            #endregion
            #region C坐标
            tmp1 = Regex.Match(nospace, "(C)" + regexFloat).Value;
            if (tmp1 != "")
            {
                tmp1 = tmp1.Replace("C", "");
                ept.c = double.Parse(tmp1);
                tmpDimension++;
            }
            else
            {
                tmp1 = Regex.Match(nospace, "(C)" + regexLong).Value;
                if (tmp1 != "")
                {
                    tmp1 = tmp1.Replace("C", "");
                    ept.c = double.Parse(tmp1);
                    tmpDimension++;
                }
            }
            #endregion
            #region Vel
            tmp1 = Regex.Match(nospace, "(F)" + regexFloat).Value;
            if (tmp1 != "")
            {
                tmp1 = tmp1.Replace("F", "");
                vel = double.Parse(tmp1);
            }
            else
            {
                tmp1 = Regex.Match(nospace, "(F)" + regexLong).Value;
                if (tmp1 != "")
                {
                    tmp1 = tmp1.Replace("F", "");
                    vel = double.Parse(tmp1);
                }
            }
            #endregion
            dimension = tmpDimension;
            return true;
        }
    }
    /// <summary>
    /// 直线指令
    /// </summary>
    public class CG01 : CGBase
    {
        public static string cmdMarkStr = "G01";
        public CPoint3D spt = new CPoint3D();
        public CPoint3D ept = new CPoint3D();
        public double A = 0, B = 0;//ab中附加运动
        /// <summary>
        /// 这一条指令给用了XYZ的那几个周
        /// 会影响最后压入到哪个指令
        /// 按照bit来算 BIT0=X BIT1=Y BIT2=Z
        /// </summary>
        public int usedAxis = 0;
        static CG01()
        {
            CGBase.registerCommand(cmdMarkStr, "CG01");
        }
        public CG01()
        {

        }
        public CG01(CPoint3D spt, CPoint3D ept)
        {
            this.spt = (CPoint3D)spt.clone();
            this.ept = (CPoint3D)ept.clone();
        }
        public override bool compileString(string cmd)
        {
            string str = cmd.Replace(" ", "");
            str = str.ToUpper();
            if (str.IndexOf(cmdMarkStr) < 0)
                return false;
            str = str.Replace("G01", "");
            str = str.Replace("G1", "");
            #region X位置
            string tmp = Regex.Match(str, "(X)" + regexFloat).Value;
            if (tmp != "")
            {
                tmp = tmp.Replace("X", "");
                ept.x = float.Parse(tmp);
                usedAxis += 1;
            }
            else
            {
                tmp = Regex.Match(str, "(X)" + regexLong).Value;
                if (tmp != "")
                {
                    tmp = tmp.Replace("X", "");
                    ept.x = float.Parse(tmp);
                    usedAxis += 1;
                }
            }
            #endregion
            #region Y位置
            tmp = Regex.Match(str, "(Y)" + regexFloat).Value;
            if (tmp != "")
            {
                tmp = tmp.Replace("Y", "");
                ept.y = float.Parse(tmp);
                usedAxis += 2;
            }
            else
            {
                tmp = Regex.Match(str, "(Y)" + regexLong).Value;
                if (tmp != "")
                {
                    tmp = tmp.Replace("Y", "");
                    ept.y = float.Parse(tmp);
                    usedAxis += 2;
                }
            }
            #endregion
            #region Z位置
            tmp = Regex.Match(str, "(Z)" + regexFloat).Value;
            if (tmp != "")
            {
                tmp = tmp.Replace("Z", "");
                ept.z = float.Parse(tmp);
                usedAxis += 4;
            }
            else
            {
                tmp = Regex.Match(str, "(Z)" + regexLong).Value;
                if (tmp != "")
                {
                    tmp = tmp.Replace("Z", "");
                    ept.z = float.Parse(tmp);
                    usedAxis += 4;
                }
            }
            #endregion
            #region Vel
            tmp = Regex.Match(str, "(F)" + regexFloat).Value;
            if (tmp != "")
            {
                tmp = tmp.Replace("F", "");
                cutVel = float.Parse(tmp);
            }
            else
            {
                tmp = Regex.Match(str, "(F)" + regexLong).Value;
                if (tmp != "")
                {
                    tmp = tmp.Replace("F", "");
                    cutVel = float.Parse(tmp);
                }
            }
            #endregion
            return true;
        }
    }
    /// <summary>
    /// 顺时针
    /// </summary>
    public class CG02 : CGBase
    {
        public static string cmdMarkStr = "G02";//如果又都号 就分开
        public CPoint2D spt = new CPoint2D();//三点构造圆的第1个点
        public CPoint2D ept = new CPoint2D();//三点构造圆的第2个点
        public CPoint2D center = new CPoint2D();//圆心
        public double I = 0, J = 0; //圆心相当于起点坐标的偏移
        public double A = 0, B = 0;//ab中附加运动
        public double radius = 10;  //半径
        public int direct = 1;      //0是顺时针  1=逆时针
        static CG02()
        {
            CGBase.registerCommand(cmdMarkStr, "CG02");
        }
        public override bool compileString(string cmd)
        {
            string nospace = cmd.Replace(" ", "");
            nospace = nospace.ToUpper();
            if (nospace.IndexOf("G02") >= 0)
            {
                try
                {
                    ept.x = float.Parse(Regex.Match(Regex.Match(nospace, "(X)" + regexFloat).Value, regexFloat).Value);
                    ept.y = float.Parse(Regex.Match(Regex.Match(nospace, "(Y)" + regexFloat).Value, regexFloat).Value);

                    I = float.Parse(Regex.Match(Regex.Match(nospace, "(I)" + regexFloat).Value, regexFloat).Value);
                    J = float.Parse(Regex.Match(Regex.Match(nospace, "(J)" + regexFloat).Value, regexFloat).Value);
                    if (nospace.IndexOf("A") >= 0)
                    {
                        A = float.Parse(Regex.Match(Regex.Match(nospace, "(A)" + regexFloat).Value, regexFloat).Value);
                    }
                    if (nospace.IndexOf("B") >= 0)
                    {
                        B = float.Parse(Regex.Match(Regex.Match(nospace, "(B)" + regexFloat).Value, regexFloat).Value);
                    }
                    cutVel = float.Parse(Regex.Match(Regex.Match(nospace, "(F)" + regexFloat).Value, regexFloat).Value);
                    direct = 0;
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
            else if (nospace.IndexOf("G03") >= 0)
            {
                try
                {
                    ept.x = float.Parse(Regex.Match(Regex.Match(nospace, "(X)" + regexFloat).Value, regexFloat).Value);
                    ept.y = float.Parse(Regex.Match(Regex.Match(nospace, "(Y)" + regexFloat).Value, regexFloat).Value);

                    I = float.Parse(Regex.Match(Regex.Match(nospace, "(I)" + regexFloat).Value, regexFloat).Value);
                    J = float.Parse(Regex.Match(Regex.Match(nospace, "(J)" + regexFloat).Value, regexFloat).Value);

                    if (nospace.IndexOf("A") >= 0)
                    {
                        A = float.Parse(Regex.Match(Regex.Match(nospace, "(A)" + regexFloat).Value, regexFloat).Value);
                    }
                    if (nospace.IndexOf("B") >= 0)
                    {
                        B = float.Parse(Regex.Match(Regex.Match(nospace, "(B)" + regexFloat).Value, regexFloat).Value);
                    }
                    cutVel = float.Parse(Regex.Match(Regex.Match(nospace, "(F)" + regexFloat).Value, regexFloat).Value);
                    direct = 1;
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
            return false;
        }
        public CG02()
        {

        }
        public CG02(CPoint2D cpt, double radius)
        {
            center.x = cpt.x;
            center.y = cpt.y;
            this.radius = radius;
        }
        /// <summary>
        /// 
        /// 线段上 距离PT1为L的一个点 有且职有一个
        /// </summary>
        /// <param name="pt">输出点</param>
        /// <param name="ept">结束点</param>
        /// <param name="L">距离</param>
        public void getSpecialPointOnLine(ref CPoint3D pt, CPoint3D ept, float L)
        {
            //获取圆
            //getCircle(pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, ref radius, ref center.X, ref center.Y);
            double tmpx = 0, tmpy = 0;
            double eptAngle = 0;
            //平移
            tmpx = ept.x - center.x;
            tmpy = ept.y - center.y;
            double addAngle = L / radius;//增量角度
            if (tmpx > 0 && tmpy >= 0)
            {
                eptAngle = Math.Atan(tmpy / tmpx);
            }
            else if (tmpx < 0 && tmpy >= 0)
            {
                eptAngle = Math.PI - Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx < 0 && tmpy <= 0)
            {
                eptAngle = Math.PI + Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx > 0 && tmpy <= 0)
            {
                eptAngle = 2 * Math.PI - Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx == 0)
            {
                if (tmpy > 0)
                {
                    eptAngle = Math.PI / 2.0;
                }
                else
                {
                    eptAngle = 1.5 * Math.PI;
                }
            }
            //旋转叫
            if (direct > 0)//逆时针
            {
                eptAngle = eptAngle - addAngle;
            }
            else
            {
                eptAngle = eptAngle + addAngle;
            }
            //计算XY
            pt.x = radius * Math.Cos(eptAngle);
            pt.y = radius * Math.Sin(eptAngle);
            pt.x += center.x;
            pt.y += center.y;
        }
        void getCircle(CPoint3D P1, CPoint3D P2, CPoint3D P3, ref double R, ref CPoint3D PCenter)
        {
            double a = 2 * (P2.x - P1.x);
            double b = 2 * (P2.y - P1.y);
            double c = P2.x * P2.x + P2.y * P2.y - P1.x * P1.x - P1.y * P1.y;
            double d = 2 * (P3.x - P2.x);
            double e = 2 * (P3.y - P2.y);
            double f = P3.x * P3.x + P3.y * P3.y - P2.x * P2.x - P2.y * P2.y;
            if ((b * d - e * a) == 0)
            {
                R = 0;
                CPoint3D tmpRst = new CPoint3D(0, 0, 0);
                PCenter = tmpRst;
                return;
            }
            double x = (b * f - e * c) / (b * d - e * a);
            double y = (d * c - a * f) / (b * d - e * a);
            double r = Math.Sqrt((double)((x - P1.x) * (x - P1.x) + (y - P1.y) * (y - P1.y)));
            R = r;
            CPoint3D pc = new CPoint3D(x, y, 0);
            PCenter = pc;

        }
        /// <summary>
        /// 3点获取一个圆
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="x3"></param>
        /// <param name="y3"></param>
        /// <param name="r"></param>
        /// <param name="cx"></param>
        /// <param name="cy"></param>
        void getCircle(double x1, double y1, double x2, double y2, double x3, double y3, ref double r, ref double cx, ref double cy)
        {
            try
            {
                if (y2 == y1 || y3 == y2) return;
                double m1, n1, m2, n2, a1, b1, a2, b2;
                m1 = (x1 + x2) / 2;
                n1 = (y1 + y2) / 2;
                //printf("\n\t第一条垂直平分线必过点为(%f,%f)", m1, n1);
                m2 = (x2 + x3) / 2;
                n2 = (y2 + y3) / 2;
                //printf("\n\t第二条垂直平分线必过点为(%f,%f)", m2, n2);
                a1 = -(x2 - x1) / (y2 - y1);
                b1 = n1 - a1 * m1;
                //printf("\n\t第一条垂直平分线为y=%fx+%f", a1, b1);
                a2 = -(x3 - x2) / (y3 - y2);
                b2 = n2 - a2 * m2;
                if (a1 == a2) return;
                //printf("\n\t第二条垂直平分线为y=%fx+%f", a2, b2);
                cx = (b2 - b1) / (a1 - a2);
                cy = a1 * cx + b1;
                r = Math.Sqrt((x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy));
            }
            catch (Exception)
            {
            }
        }
    }
    /// <summary>
    /// 逆时针
    /// </summary>
    public class CG03 : CGBase
    {
        public static string cmdMarkStr = "G03";//如果又都号 就分开
        public CPoint2D spt = new CPoint2D();//三点构造圆的第1个点
        public CPoint2D ept = new CPoint2D();//三点构造圆的第2个点
        public CPoint2D center = new CPoint2D();//圆心
        public double I = 0, J = 0; //圆心相当于起点坐标的偏移
        public double A = 0, B = 0;//ab中附加运动
        public double radius = 10;  //半径
        public int direct = 0;      //0是顺时针  1=逆时针
        static CG03()
        {
            CGBase.registerCommand(cmdMarkStr, "CG03");
        }
        public CG03()
        {

        }
        public CG03(CPoint2D cpt, double radius)
        {
            center.x = cpt.x;
            center.y = cpt.y;
            this.radius = radius;
        }
        public override bool compileString(string cmd)
        {
            string nospace = cmd.Replace(" ", "");
            nospace = nospace.ToUpper();
            if (nospace.IndexOf("G02") >= 0)
            {
                try
                {
                    ept.x = float.Parse(Regex.Match(Regex.Match(nospace, "(X)" + regexFloat).Value, regexFloat).Value);
                    ept.y = float.Parse(Regex.Match(Regex.Match(nospace, "(Y)" + regexFloat).Value, regexFloat).Value);

                    I = float.Parse(Regex.Match(Regex.Match(nospace, "(I)" + regexFloat).Value, regexFloat).Value);
                    J = float.Parse(Regex.Match(Regex.Match(nospace, "(J)" + regexFloat).Value, regexFloat).Value);
                    if (nospace.IndexOf("A") >= 0)
                    {
                        A = float.Parse(Regex.Match(Regex.Match(nospace, "(A)" + regexFloat).Value, regexFloat).Value);
                    }
                    if (nospace.IndexOf("B") >= 0)
                    {
                        B = float.Parse(Regex.Match(Regex.Match(nospace, "(B)" + regexFloat).Value, regexFloat).Value);
                    }
                    cutVel = float.Parse(Regex.Match(Regex.Match(nospace, "(F)" + regexFloat).Value, regexFloat).Value);
                    direct = 0;
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
            else if (nospace.IndexOf("G03") >= 0)
            {
                try
                {
                    ept.x = float.Parse(Regex.Match(Regex.Match(nospace, "(X)" + regexFloat).Value, regexFloat).Value);
                    ept.y = float.Parse(Regex.Match(Regex.Match(nospace, "(Y)" + regexFloat).Value, regexFloat).Value);

                    I = float.Parse(Regex.Match(Regex.Match(nospace, "(I)" + regexFloat).Value, regexFloat).Value);
                    J = float.Parse(Regex.Match(Regex.Match(nospace, "(J)" + regexFloat).Value, regexFloat).Value);

                    if (nospace.IndexOf("A") >= 0)
                    {
                        A = float.Parse(Regex.Match(Regex.Match(nospace, "(A)" + regexFloat).Value, regexFloat).Value);
                    }
                    if (nospace.IndexOf("B") >= 0)
                    {
                        B = float.Parse(Regex.Match(Regex.Match(nospace, "(B)" + regexFloat).Value, regexFloat).Value);
                    }
                    cutVel = float.Parse(Regex.Match(Regex.Match(nospace, "(F)" + regexFloat).Value, regexFloat).Value);
                    direct = 1;
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
            return false;
        }
        /// <summary>
        /// 
        /// 线段上 距离PT1为L的一个点 有且职有一个
        /// </summary>
        /// <param name="pt">输出点</param>
        /// <param name="ept">结束点</param>
        /// <param name="L">距离</param>
        public void getSpecialPointOnLine(ref CPoint3D pt, CPoint3D ept, float L)
        {
            //获取圆
            //getCircle(pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, ref radius, ref center.X, ref center.Y);
            double tmpx = 0, tmpy = 0;
            double eptAngle = 0;
            //平移
            tmpx = ept.x - center.x;
            tmpy = ept.y - center.y;
            double addAngle = L / radius;//增量角度
            if (tmpx > 0 && tmpy >= 0)
            {
                eptAngle = Math.Atan(tmpy / tmpx);
            }
            else if (tmpx < 0 && tmpy >= 0)
            {
                eptAngle = Math.PI - Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx < 0 && tmpy <= 0)
            {
                eptAngle = Math.PI + Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx > 0 && tmpy <= 0)
            {
                eptAngle = 2 * Math.PI - Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx == 0)
            {
                if (tmpy > 0)
                {
                    eptAngle = Math.PI / 2.0;
                }
                else
                {
                    eptAngle = 1.5 * Math.PI;
                }
            }
            //旋转叫
            if (direct > 0)//逆时针
            {
                eptAngle = eptAngle - addAngle;
            }
            else
            {
                eptAngle = eptAngle + addAngle;
            }
            //计算XY
            pt.x = radius * Math.Cos(eptAngle);
            pt.y = radius * Math.Sin(eptAngle);
            pt.x += center.x;
            pt.y += center.y;
        }
        void getCircle(CPoint3D P1, CPoint3D P2, CPoint3D P3, ref double R, ref CPoint3D PCenter)
        {
            double a = 2 * (P2.x - P1.x);
            double b = 2 * (P2.y - P1.y);
            double c = P2.x * P2.x + P2.y * P2.y - P1.x * P1.x - P1.y * P1.y;
            double d = 2 * (P3.x - P2.x);
            double e = 2 * (P3.y - P2.y);
            double f = P3.x * P3.x + P3.y * P3.y - P2.x * P2.x - P2.y * P2.y;
            if ((b * d - e * a) == 0)
            {
                R = 0;
                CPoint3D tmpRst = new CPoint3D(0, 0, 0);
                PCenter = tmpRst;
                return;
            }
            double x = (b * f - e * c) / (b * d - e * a);
            double y = (d * c - a * f) / (b * d - e * a);
            double r = Math.Sqrt((double)((x - P1.x) * (x - P1.x) + (y - P1.y) * (y - P1.y)));
            R = r;
            CPoint3D pc = new CPoint3D(x, y, 0);
            PCenter = pc;

        }
        /// <summary>
        /// 3点获取一个圆
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="x3"></param>
        /// <param name="y3"></param>
        /// <param name="r"></param>
        /// <param name="cx"></param>
        /// <param name="cy"></param>
        void getCircle(double x1, double y1, double x2, double y2, double x3, double y3, ref double r, ref double cx, ref double cy)
        {
            try
            {
                if (y2 == y1 || y3 == y2) return;
                double m1, n1, m2, n2, a1, b1, a2, b2;
                m1 = (x1 + x2) / 2;
                n1 = (y1 + y2) / 2;
                //printf("\n\t第一条垂直平分线必过点为(%f,%f)", m1, n1);
                m2 = (x2 + x3) / 2;
                n2 = (y2 + y3) / 2;
                //printf("\n\t第二条垂直平分线必过点为(%f,%f)", m2, n2);
                a1 = -(x2 - x1) / (y2 - y1);
                b1 = n1 - a1 * m1;
                //printf("\n\t第一条垂直平分线为y=%fx+%f", a1, b1);
                a2 = -(x3 - x2) / (y3 - y2);
                b2 = n2 - a2 * m2;
                if (a1 == a2) return;
                //printf("\n\t第二条垂直平分线为y=%fx+%f", a2, b2);
                cx = (b2 - b1) / (a1 - a2);
                cy = a1 * cx + b1;
                r = Math.Sqrt((x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy));
            }
            catch (Exception)
            {
            }
        }
    }
    /// <summary>
    /// 一个整圆
    /// </summary>
    public class CCmdCircle : CGBase
    {
        public static string cmdMarkStr = "整圆";
        public CPoint2D center = new CPoint2D();
        public int direct = 0;//0=顺时针  1= 逆时针
        public CPoint2D spt = new CPoint2D();
        public CPoint2D ept = new CPoint2D();
        public double I = 0, J = 0;//圆心相对于圆起点的偏移
        public double A = 0, B = 0;//ab中附加运动
        public double radius = 10;
        static CCmdCircle()
        {
            CGBase.registerCommand(cmdMarkStr, "CCmdCircle");
        }
        public CCmdCircle()
        {
            radius = 10;
            center.x = center.y = 0;
        }
        public CCmdCircle(CPoint2D cpt, double radius)
        {
            center.x = cpt.x;
            center.y = cpt.y;
            this.radius = radius;
        }
        /// <summary>
        /// TODO:还没有写
        /// </summary>
        /// <param name="pt1"></param>
        /// <param name="pt2"></param>
        /// <param name="pt3"></param>
        public CCmdCircle(CPoint2D pt1, CPoint2D pt2, CPoint2D pt3)
        {
        }

        public override bool compileString(string cmd)
        {
            return false;
        }
        /// <summary>
        /// 
        /// 线段上 距离PT1为L的一个点 有且职有一个
        /// </summary>
        /// <param name="pt">输出点</param>
        /// <param name="ept">结束点</param>
        /// <param name="L">距离</param>
        public void getSpecialPointOnLine(ref CPoint3D pt, CPoint3D ept, float L)
        {
            //获取圆
            double tmpx = 0, tmpy = 0;
            double eptAngle = 0;
            //平移
            tmpx = ept.x - center.x;
            tmpy = ept.y - center.y;
            double addAngle = L / radius;//增量角度
            if (tmpx > 0 && tmpy >= 0)
            {
                eptAngle = Math.Atan(tmpy / tmpx);
            }
            else if (tmpx < 0 && tmpy >= 0)
            {
                eptAngle = Math.PI - Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx < 0 && tmpy <= 0)
            {
                eptAngle = Math.PI + Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx > 0 && tmpy <= 0)
            {
                eptAngle = 2 * Math.PI - Math.Atan(Math.Abs(tmpy / tmpx));
            }
            else if (tmpx == 0)
            {
                if (tmpy > 0)
                {
                    eptAngle = Math.PI / 2.0;
                }
                else
                {
                    eptAngle = 1.5 * Math.PI;
                }
            }
            //旋转叫
            if (direct > 0)//逆时针
            {
                eptAngle = eptAngle - addAngle;
            }
            else
            {
                eptAngle = eptAngle + addAngle;
            }
            //计算XY
            pt.x = radius * Math.Cos(eptAngle);
            pt.y = radius * Math.Sin(eptAngle);
            pt.x += center.x;
            pt.y += center.y;
        }
    }
    #endregion
}
